﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Threading;
using EzDesk.DevHelper.DbMgr.Views;
using Microsoft.SqlServer.Management.Smo;

namespace EzDesk.DevHelper.DbMgr.Presenters
{
    public class DbMainPresenter:DbMgrPresenterBase
    {
        private IMainFormView _view;


        public DbMainPresenter(IMainFormView mainForm)
        {
            _view = mainForm;
            _logView = mainForm;
        }

        #region [ private methods ] 
        private void backupDatabaseToFile(string databaseName, string fullBackupName)
        {
            Server srv = new Server(_dataSourceName);
            Backup backup = new Backup();
            backup.Action = BackupActionType.Database;
            backup.Database = databaseName;
            backup.Incremental = false;
            backup.Devices.Add(new BackupDeviceItem(fullBackupName, DeviceType.File));
            backup.Initialize = true;

            backup.SqlBackup(srv);
        }

        private void restoreBackupFile(string databaseName, string backupName)
        {
            Server srv = new Server(_dataSourceName);
            Restore restore = new Restore();
            restore.Action = RestoreActionType.Database;
            restore.Database = databaseName;
            restore.Devices.Add(new BackupDeviceItem(backupName, DeviceType.File));

            if (srv.Databases.Contains(databaseName))
            {
                _view.WriteLine("找到已存在的数据库，尝试删除。。");
                var database = srv.Databases[databaseName];
                if (database.UserAccess != DatabaseUserAccess.Single)
                {
                    database.UserAccess = DatabaseUserAccess.Single;
                    database.Alter(TerminationClause.RollbackTransactionsImmediately);
                    database.Refresh();
                }
                database.Drop();
            }
            restore.SqlRestore(srv);
        }

        private bool isDatabaseBackupFile(string filename)
        {
            return _databaseNameList.Any(filename.Contains) &&
                   Path.GetExtension(filename).ToLower() == ".bak";
        }
        #endregion



        public dynamic ConnectToServer(string targetServerName, string instanceName)
        {
            // 发起一个到master的连接，如果成功则认为目标数据库服务器名称正确
            _dataSourceName = targetServerName + @"\" + instanceName;
            var connStr = getConnectionString("master");

            bool connSuccess = true;
            try
            {
                using (var conn = new SqlConnection(connStr))
                {
                    conn.Open();
                    var cmd = new SqlCommand("SELECT * FROM spt_monitor", conn);
                    cmd.ExecuteNonQuery();
                }
                _view.WriteLine("连接到服务器 " + _dataSourceName + " 成功");
            }
            catch (SqlException ex)
            {
                connSuccess = false;
                _view.WriteLine("连接到服务器 " + _dataSourceName + " 失败");
            }

            // 没有抛出异常);
            return new
                       {
                           IsServerAvailable = connSuccess,
                           ServerName = connSuccess ? _dataSourceName : "连接失败",
                       };
        }

        public void FindDatabaseSchema()
        {
            const string relDatabasePath = @"\Database\{0}\sql\debug\{1}.deploymanifest";

            var ezdeskPath = Utility.GetEzDeskRootPath();

            foreach (var databaseName in _databasePrjNamelist)
            {
                var fullName = string.Format(ezdeskPath + relDatabasePath, databaseName, databaseName);

                if (File.Exists(fullName))
                {
                    // 如果找到了目标文件，则把目标文件夹下所有文件复制到当前文件夹下面

                    _view.WriteLine("找到项目中的数据库结构文件: " + fullName);

                    var allFiles = Directory.GetFiles(Path.GetDirectoryName(fullName));

                    foreach (var fileName in allFiles)
                    {
                        File.Copy(fileName, Path.GetFileName(fileName), true);
                    }
                }
            }

            RefreshDataSchema();
        }

        public void RefreshDataSchema()
        {
            List<string> schemaList = getAvailableSchemaList();

            _view.RefreshSchemaList(schemaList);
        }

        

        public void UpdateSchema(List<string> dataSchemaList)
        {
            refreshDatabaseSchema(dataSchemaList);
        }


        public void RefreshCurrentDatabases()
        {
            if (!_dataSourceName.StartsWith(".")) return;

            var result = new List<string>();
            foreach (var databaseName in _databaseNameList)
            {
                string connStr = getConnectionString(databaseName);
                bool connSuccess = true;
                try
                {
                    using (var conn = new SqlConnection(connStr))
                    {
                        conn.Open();
                    }
                }
                catch (SqlException)
                {
                    connSuccess = false;
                }
                if (connSuccess)
                {
                    result.Add(databaseName);
                }
            }
            _view.RefreshDatabaseList(result);
        }

        public void BackupDatabase(List<string> result)
        {
            foreach (var databaseName in result)
            {
                try
                {
                    if (string.IsNullOrEmpty(databaseName)) break;

                    var backupName = _dataSourceName.Replace("\\", "_") + "_" + databaseName + "_" +
                                     DateTime.Now.ToString("yyyyMMddHHmmss") + ".bak";
                    var fullBackupName = Path.GetFullPath(".") + "\\" + backupName;

                    backupDatabaseToFile(databaseName, fullBackupName);

                    _view.WriteLine("备份数据库 " + databaseName + " 完成 - " + fullBackupName);
                }
                catch (Exception ex)
                {
                    _view.WriteLine("备份数据库 " + databaseName + " 失败");
                }
            }

            RefreshBackups();
        }

        /// <summary>
        /// 备份到初始化数据
        /// </summary>
        /// <param name="result"></param>
        public void BackupToInit(List<string> result)
        {
            foreach (var databaseName in result)
            {
                try
                {
                    if (string.IsNullOrEmpty(databaseName)) break;

                    var backupName = "INIT_" + databaseName + ".bak";
                    var fullBackupName = Path.GetFullPath(".") + "\\" + backupName;

                    backupDatabaseToFile(databaseName, fullBackupName);

                    _view.WriteLine("备份初始化数据库 " + databaseName + " 完成 - " + fullBackupName);
                }
                catch (Exception ex)
                {
                    _view.WriteLine("备份初始化数据库 " + databaseName + " 失败");
                }
            }
            RefreshBackups();
        }

        public void RefreshBackups()
        {
            var result = new List<string>();
            //在当前文件夹下找
            var allFiles = Directory.GetFiles(Environment.CurrentDirectory);
            foreach (var filename in allFiles)
            {
                if (isDatabaseBackupFile(filename))
                {
                    result.Add(Path.GetFileName(filename));
                }
            }

            _view.RefreshBackupList(result);
        }

        public void RestoreFromBackups(List<string> backupList)
        {
            foreach (var backupName in backupList)
            {
                if (!File.Exists(backupName))
                {
                    _view.WriteLine("备份文件： " + backupName + " 不存在");
                }
                string theDatabaseName = "";
                foreach (var databaseName in _databaseNameList)
                {
                    if (backupName.Contains(databaseName))
                    {
                        theDatabaseName = databaseName;
                        break;
                    }
                }
                if(string.IsNullOrEmpty(theDatabaseName))
                {
                    _view.WriteLine("备份文件： " + backupName + " 错误！");
                    break;
                }

                try
                {
                    restoreBackupFile(theDatabaseName, Path.GetFullPath(backupName));

                    _view.WriteLine("恢复数据库 " + theDatabaseName + " 完成");
                }
                catch (Exception ex)
                {
                    _view.WriteLine("恢复数据库 " + theDatabaseName + " 失败 : " + ex.Message);
                }
            }

        }

    }
}